package com.xlyy.modbus.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ghgande.j2mod.modbus.facade.ModbusTCPMaster;
import com.ghgande.j2mod.modbus.procimg.Register;
import com.ghgande.j2mod.modbus.util.BitVector;
import com.xlyy.modbus.bo.MyTestresultBo;
import com.xlyy.modbus.entity.MyData;
import com.xlyy.modbus.entity.MyProperity;
import com.xlyy.modbus.entity.MyTestresult;
import com.xlyy.modbus.property.Device;
import com.xlyy.modbus.service.IMyDataService;
import com.xlyy.modbus.service.IMyHeadinfoService;
import com.xlyy.modbus.service.IMyProperityService;
import com.xlyy.modbus.service.IMyTestresultService;
import com.xlyy.modbus.vo.MyDevice;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zhoucanji
 * @since 2024-04-28
 */
@RestController
@RequestMapping("/myProperity")
public class MyProperityController {
    @Value("${myproperty.modbus.ip}")
    private String serverAddress;
    @Value("${myproperty.modbus.port}")
    private int serverPort;
    @Value("${myproperty.modbus.differential}")
    private BigDecimal differential;
    @Autowired
    private IMyProperityService myProperityService;
    @Autowired
    private IMyDataService myDataService;
    @Autowired
    private IMyHeadinfoService myHeadinfoService;

    @Autowired
    private IMyTestresultService myTestresultService;

    ExecutorService executor = Executors.newSingleThreadExecutor();
//    private static AtomicBoolean isPaused = new AtomicBoolean(true);
    private String pch=null;
    String categorize=null;
    int ref=0;

    @PostConstruct
    public void init() {
        select();
        executor.execute(()->{
            ModbusTCPMaster modbusTCPMaster = new ModbusTCPMaster(serverAddress, serverPort);
            while (!modbusTCPMaster.isConnected()){
                try {
                    modbusTCPMaster.connect();
                    System.out.println("====>连接成功");
                    while (true){
                        collectRead(modbusTCPMaster);
                    }
                } catch (Exception e) {
                    System.out.println("====>断线重连");
                } finally {
                    if(modbusTCPMaster.isConnected()){
                        modbusTCPMaster.disconnect();
                    }
                }
            }
        });
    }

//    @RequestMapping("/colletStart")
//    public void colletStart(){
//        isPaused.set(true);
//    }
//
//    @RequestMapping("/colletStop")
//    public void colletStop(){
//        isPaused.set(false);
//    }

//    @RequestMapping("/state")
//    public String state(){
//        return  isPaused.get()?"colletStart":"colletStop";
//    }


    @RequestMapping("/select")
    public List<MyProperity> select() {
        LambdaQueryWrapper<MyProperity> lambdaQueryWrapper=new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(MyProperity::getDel,"0");
        List<MyProperity> list = myProperityService.list(lambdaQueryWrapper);
        Map<String, List<MyProperity>> collect = list.stream().collect(Collectors.groupingBy(MyProperity::getCategorize, Collectors.toList()));
        Device.categorize=collect;
        for (String categorize : collect.keySet()) {
            List<MyProperity> myProperities = collect.get(categorize).stream()
                    .sorted(Comparator.comparing(MyProperity::getSort))
                    .toList();
            MyDevice device = new MyDevice();
            device.setCategorize(myProperities.get(0));
            device.setSv(myProperities.get(1));
            device.setPv(myProperities.stream().skip(2).toList());
            Device.devices.add(device);

        }
        return list;
    }

    @RequestMapping("/collection")
    public String collection() {
        StringBuilder sb = new StringBuilder();
        try {
            ModbusTCPMaster modbusTCPMaster = new ModbusTCPMaster(serverAddress, serverPort);
            modbusTCPMaster.connect();
            List<MyData> datas = collectRead(modbusTCPMaster);
            if (datas != null && datas.size() > 0) {

                for (MyData data : datas) {
                    sb.append(data.getCategorize() + "")
                            .append(",压力设定SV值" + data.getSv() + "MPA");
                    if (data.getPv1().compareTo(new BigDecimal(Integer.MIN_VALUE))!=0) {
                        sb.append(",第一个压力PV值：" + data.getPv1());
                    }
                    if (data.getPv2().compareTo(new BigDecimal(Integer.MIN_VALUE))!=0) {
                        sb.append(",第二个压力PV值：" + data.getPv2());
                    }
                    if (data.getPv3().compareTo(new BigDecimal(Integer.MIN_VALUE))!=0) {
                        sb.append(",第三个压力PV值：" + data.getPv3());
                    }
                    if (data.getPv4().compareTo(new BigDecimal(Integer.MIN_VALUE))!=0) {
                        sb.append(",第四个压力PV值：" + data.getPv4());
                    }
                    if (data.getPv5().compareTo(new BigDecimal(Integer.MIN_VALUE))!=0) {
                        sb.append(",第五个压力PV值：" + data.getPv5());
                    }
                    sb.append("<br>");
                }
            }
            modbusTCPMaster.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }



    private List<MyData> collectRead(ModbusTCPMaster modbusTCPMaster) throws Exception {
        List<MyData> datas = new ArrayList<>();
        MyData dbMyData = tranferPojo(myHeadinfoService.getMyHeadinfoById(),MyData.class);
        MyTestresultBo myTestresultBo=new MyTestresultBo();

        for (MyDevice device : Device.devices) {
            MyData data=dbMyData;
            int read = read(modbusTCPMaster, device.getCategorize().getCategorize() + device.getCategorize().getName(), device.getCategorize().getRef());
            if (read ==0) {
                if(pch!=null && device.getCategorize().getRef()==ref){
                    MyData startData = myDataService.startData(pch);
                    MyData endData = myDataService.endData(pch);
                    List<BigDecimal> list=new ArrayList<>();
                    int num=Device.categorize.get(categorize).size()-2;
                    if(num>=1){
                        list.add(dp(startData.getPv1(),endData.getPv1()));
                    }
                    if(num>=2){
                        list.add(dp(startData.getPv2(),endData.getPv2()));
                    }
                    if(num>=3){
                        list.add(dp(startData.getPv3(),endData.getPv3()));
                    }
                    if(num>=4){
                        list.add( dp(startData.getPv4(),endData.getPv4()));
                    }
                    if(num>=5){
                        list.add(dp(startData.getPv5(),endData.getPv5()));
                    }
                    boolean b = list.stream().allMatch(v -> differential.compareTo(v)==1);
                    long s=(endData.getCrateTime().getTime()-startData.getCrateTime().getTime())/1000;
                    MyTestresult myTestresult=new MyTestresult();
                    myTestresult.setPch(pch);
                    myTestresult.setSyjg(b?"OK":"NO");
                    myTestresult.setSyyl(startData.getSv().toString());
                    myTestresult.setBysj(String.valueOf(s));
//                    myTestresult.setKtbh(startData.getKtph());
                    myTestresult.setCategorize(categorize);
                    myTestresultService.saveOrUpdate(myTestresult);
                    pch=null;
                    categorize=null;
                    ref=0;
                };
               if(pch==null){
                   MyTestresult myTestresult = myTestresultService.lastMyTestresult();
                   if(myTestresult!=null){
                       myTestresultBo=tranferPojo(myTestresult, MyTestresultBo.class);
                       myTestresultBo.setState("0");
                   }else {
                       myTestresultBo.setState("1");
                   }
                   WebsocketController.sendMessage(myTestresultBo,"modbusSystem");
               }


                //没有启动测试
                continue;
            }
            if(pch==null) pch=String.valueOf(System.currentTimeMillis());
            categorize=device.getCategorize().getCategorize();
            ref=device.getCategorize().getRef();
            data.setCategorize(categorize);

            //标准职
            BigDecimal sv = readBigDecimal(modbusTCPMaster, device.getSv().getCategorize() + device.getSv().getName(), device.getSv().getRef());
            data.setSv(sv);
            data.setPv1(readPv(device.getPv(), 1, modbusTCPMaster));
            data.setPv2(readPv(device.getPv(), 2, modbusTCPMaster));
            data.setPv3(readPv(device.getPv(), 3, modbusTCPMaster));
            data.setPv4(readPv(device.getPv(), 4, modbusTCPMaster));
            data.setPv5(readPv(device.getPv(), 5, modbusTCPMaster));
            data.setC6(readPv(device.getPv(), 6, modbusTCPMaster));
            data.setD7(readPvInt(device.getPv(), 7, modbusTCPMaster));
            data.setPch(pch);
            datas.add(data);
            myTestresultBo.setState("1");
            WebsocketController.sendMessage(myTestresultBo,"modbusSystem");
        }
        if (datas != null && datas.size() > 0) {
            myDataService.saveBatch(datas);
        }

        return datas;
    }

    private BigDecimal readPv(List<MyProperity> pvs, int i, ModbusTCPMaster modbusTCPMaster) throws Exception {
        if (i > pvs.size()) {
            return new BigDecimal(Integer.MIN_VALUE);
        }
        MyProperity pv = pvs.get(i - 1);
//        int open = read(modbusTCPMaster, pv.getCategorize() + pv.getName(), pv.getRefRef());
//        if (open==0) {
//            return new BigDecimal(Integer.MIN_VALUE);
//        }
        return readBigDecimal(modbusTCPMaster, pv.getCategorize() + pv.getName(), pv.getRef());
    }

    private BigDecimal readPvInt(List<MyProperity> pvs, int i, ModbusTCPMaster modbusTCPMaster) throws Exception {
        if (i > pvs.size()) {
            return new BigDecimal(Integer.MIN_VALUE);
        }
        MyProperity pv = pvs.get(i - 1);
//        int open = read(modbusTCPMaster, pv.getCategorize() + pv.getName(), pv.getRefRef());
//        if (open==0) {
//            return new BigDecimal(Integer.MIN_VALUE);
//        }
        return new BigDecimal(read(modbusTCPMaster, pv.getCategorize() + pv.getName(), pv.getRef()));
    }

    public static int read(ModbusTCPMaster modbusTCPMaster, String name, int ref) throws Exception {
        Register[] h = modbusTCPMaster.readMultipleRegisters(1, ref, 1);
        System.out.println(ref + "：" + h[0].getValue());
        return h[0].getValue();
    }

    public static BigDecimal readBigDecimal (ModbusTCPMaster modbusTCPMaster, String name, int ref) throws Exception {
        Register[] h = modbusTCPMaster.readMultipleRegisters(1, ref, 1);
        System.out.println(ref + "：" + h[0].getValue());
        return new BigDecimal(h[0].getValue()).movePointLeft(1);
    }

    public static boolean readBit(ModbusTCPMaster modbusTCPMaster, String name, int ref) throws Exception {
        BitVector bitVector = modbusTCPMaster.readCoils(1, ref, 1);
        System.out.println(ref + "：" + bitVector.getBit(0));
        return bitVector.getBit(0);
    }

    public static void reads(ModbusTCPMaster modbusTCPMaster, String name, int ref) throws Exception {
        Register[] h = modbusTCPMaster.readMultipleRegisters(1, ref, 1);//保持
        for (Register register : h) {
            System.out.println(name + "：" + register.getValue());
        }
    }

    public static void readSwitch(ModbusTCPMaster modbusTCPMaster, String name) throws Exception {
        Register[] h = modbusTCPMaster.readMultipleRegisters(1, 590, 5);
        System.out.print("590：" + h[0].getValue());
        System.out.print(",591：" + h[1].getValue());
        System.out.print(",592：" + h[2].getValue());
        System.out.print(",593：" + h[3].getValue());
        System.out.println(",594：" + h[4].getValue());
    }

    public <T, R> R tranferPojo(T pojo, Class<R> clz) {
        try {
            R r = clz.newInstance();
            BeanUtils.copyProperties(pojo, r);
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public BigDecimal dp(BigDecimal startData, BigDecimal endData){
        BigDecimal v1=startData.compareTo(BigDecimal.ZERO) < 0? BigDecimal.ZERO:startData;
        BigDecimal v2=endData.compareTo(BigDecimal.ZERO) < 0? BigDecimal.ZERO:endData;
        return v1.subtract(v2);
    }


}
